package com.mp.approvalreq.util;


import com.mp.approvalreq.entity.Request;
import com.mp.approvalreq.entity.dto.RequestInfoDTO;
import com.mp.user.entity.User;
import com.plusmoney.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ListHelper {

    private static final Logger logger = LoggerFactory.getLogger(ListHelper.class);


    public static boolean isNullEmpty(List<?> list) {
        return list == null || list.isEmpty();
    }

    public static boolean isNotNullEmpty(List<?> list) {
        return !isNullEmpty(list);
    }


    /**
     * 判断第一个list是否是第二个list的子集
     * 两个list都不能为空,参数类型需要保持一致
     *
     * @param subList
     * @param parentList
     * @return
     */
    public static boolean isSubList(List<?> subList, List<?> parentList) {
        if (isNullEmpty(subList) || isNullEmpty(parentList)) {
            return false;
        }

        for (Object o : subList) {
            if (!findElement(parentList, o)) {
                return false;
            }
        }

        return true;
    }


    /**
     * 判断两list是否有相等的元素
     * 当其中一个List为空或为null时返回false;
     * 当两个list的数据类型不一致时返回false;
     *
     * @param list1
     * @param list2
     * @return
     */
    public static boolean hasEqualsElement(List<?> list1, List<?> list2) {
        if (isNullEmpty(list1) || isNullEmpty(list2)) {
            return false;
        }

        for (Object o : list1) {
            if (findElement(list2, o)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断list集合中是否存在obj元素
     *
     * @param list
     * @param obj
     * @return
     */
    public static boolean findElement(List<?> list, Object obj) {
        for (Object item : list) {
            if (Objects.equals(item, obj)) {
                return true;
            }
        }
        return false;
    }


    public static boolean equals(List<Integer> list1, List<Integer> list2) {
        if (isNullEmpty(list1) && isNotNullEmpty(list2)) {
            return false;
        } else if (isNotNullEmpty(list1) && isNullEmpty(list2)) {
            return false;
        } else if (list1.size() != list2.size()) {
            return false;
        } else if (isNullEmpty(list1) && isNullEmpty(list2)) {
            return true;
        }

        for (int i = 0; i < list1.size(); i++) {
            if (!list1.get(i).equals(list2.get(i))) {
                return false;
            }
        }

        return true;
    }


    public static <T> String list2string(List<T> list) {
        String str = list.toString().substring(1, list.toString().length() - 1);
        return str.replaceAll(" ", "");
    }


    public static List<String> string2StringList(String string) {
        List<String> list = new LinkedList<>();
        if (StringUtils.isEmpty(string)) {
            return list;
        }

        list.addAll(Arrays.asList(string.split(",")));

        return list;
    }


    public static List<String> string2NumStringList(String string) {
        List<String> list = new LinkedList<>();
        if (StringUtils.isEmpty(string)) {
            return list;
        }

        for (String str : string.split(",")) {
            if (isPositiveNum(str)) {
                list.add(str);
            }
        }

        return list;
    }


    public static List<Integer> string2IntegerList(String string) {
        List<Integer> list = new LinkedList<>();
        if (StringUtils.isEmpty(string)) {
            return list;
        }

        for (String str : string.split(",")) {
            if (isPositiveNum(str)) {
                list.add(Integer.valueOf(str));
            }
        }

        return list;
    }

    public static List<Integer> getTemplateIdList(List<RequestInfoDTO> requestInfoDTOS) {
        List<Integer> templateIds = new ArrayList<>();

        if (isNullEmpty(requestInfoDTOS)) {
            return templateIds;
        }

        for (RequestInfoDTO requestInfoDTO : requestInfoDTOS) {
            templateIds.add(requestInfoDTO.getTemplateId());
        }

        return templateIds;
    }


    public static String getTemplateIds(List<RequestInfoDTO> requestInfoDTOS) {
        if (isNullEmpty(requestInfoDTOS)) {
            return null;
        }

        List<Integer> templateIds = new ArrayList<>(requestInfoDTOS.size());
        for (RequestInfoDTO requestInfoDTO : requestInfoDTOS) {
            templateIds.add(requestInfoDTO.getTemplateId());
        }

        return list2string(templateIds);
    }


    public static List<Integer> getRequestIds(List<RequestInfoDTO> requests) {
        List<Integer> requestIds = new ArrayList<>();

        if (isNullEmpty(requests)) {
            return requestIds;
        }

        for (RequestInfoDTO requestInfoDTO : requests) {
            requestIds.add(requestInfoDTO.getRequestId());
        }

        return requestIds;
    }


    public static List<Integer> getRequestIdList(List<Request> requests) {
        List<Integer> requestIdList = new ArrayList<>(requests.size());

        if (isNullEmpty(requests)) {
            return requestIdList;
        }

        for (Request request : requests) {
            requestIdList.add(request.getRequestDkey());
        }

        return requestIdList;
    }


    public static List<Integer> getContactIdList(List<User> users) {
        List<Integer> contactIds = new LinkedList<>();
        if (isNullEmpty(users)) {
            return contactIds;
        }

        for (User user : users) {
            contactIds.add(user.getContactId());
        }

        return contactIds;
    }

    public static String getContactIds(List<User> users) {
        StringBuilder contactIds = new StringBuilder();

        for (int i = 0; i < users.size(); i++) {
            contactIds.append(users.get(i).getContactId());
            if (users.size() - i > 1) {
                contactIds.append(",");
            }
        }

        return contactIds.toString();
    }


    public static List<Integer> getCompanyInfoIdList(List<User> users) {
        List<Integer> companyInfoIdList = new LinkedList<>();
        if (isNullEmpty(users)) {
            return companyInfoIdList;
        }

        for (User user : users) {
            companyInfoIdList.add(user.getCompanyInfoId());
        }

        return companyInfoIdList;
    }


    /**
     * 两个list中相等的元素
     *
     * @param one
     * @param two
     * @return
     */
    public static List<Integer> getEqualsNums(List<Integer> one, List<Integer> two) {
        List<Integer> res = new LinkedList<>();
        for (int i : one) {
            for (int j : two) {
                if (i == j) {
                    res.add(i);
                    break;
                }
            }
        }
        return res;
    }


    /**
     * 两个list中相等元素的个数
     *
     * @param one
     * @param two
     * @return
     */
    public static int getEqualParam(List<Integer> one, List<Integer> two) {
        return getEqualsNums(one, two).size();
    }


    /**
     * 获取两个列表的交集
     *
     * @param list1
     * @param list2
     * @return
     */
    public static List<Integer> getOverLapList(List<Integer> list1, List<Integer> list2) {
        if (Utils.isEmpty(list1) || Utils.isEmpty(list2)) {
            return new ArrayList<>();
        }
        Set<Integer> set = new HashSet<>();
        for (Integer integer : list1) {
            if (list2.contains(integer)) {
                set.add(integer);
            }
        }
        return new ArrayList<>(set);
    }

    /**
     * 获取两个List的不同元素 返回第一个参数多出来的
     *
     * @param <T>
     * @param listDb
     * @param listNew
     * @return
     */
    public static <T> List<T> getListDifferent(List<T> listDb, List<T> listNew) {
        Map<T, Integer> map = new LinkedHashMap<>();
        for (T o : listDb) {
            logger.info("listDb Object **** : " + o);
            map.put(o, 1);
        }
        for (T o : listNew) {
            logger.info("listNew Object **** : " + o);
            logger.info("map.get Object **** : " + map.get(o));
            if (map.get(o) != null) {
                map.put(o, 2);
            }
        }
        List<T> diff = new ArrayList<>();
        for (Map.Entry<T, Integer> entry : map.entrySet()) {
            logger.info("entry.getValue() **** : " + entry.getValue());
            if (entry.getValue() == 1) {
                logger.info("entry.getKey() **** : " + entry.getKey());
                diff.add(entry.getKey());
            }
        }
        logger.info(diff.toString());
        return diff;
    }

    public static <T> List<T> sortByOccurrenceNumber(List<T> list) {
        Map<T, Integer> map = new HashMap<>();

        for (T t : list) {
            map.merge(t, 1, Integer::sum);
        }

        List<Map.Entry<T, Integer>> entryList = new ArrayList<>(map.entrySet());

        entryList.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));

        List<T> resultList = new LinkedList<T>();
        for (Map.Entry<T, Integer> entry : entryList) {
            resultList.add(entry.getKey());
        }

        return resultList;
    }

    public static String listToString(List<String> list) {
        if (list != null && list.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < list.size(); i++) {
                sb.append(list.get(i));
                if (list.size() - i > 1) {
                    sb.append(",");
                }
            }
            return sb.toString();
        } else {
            return null;
        }
    }

    public static String collectionToString(Collection<Integer> collection) {
        if (Utils.isEmpty(collection)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (Integer i : collection) {
            sb.append(i).append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    public static boolean isPositiveNum(String str) {
        if (StringUtils.isEmpty(str)) {
            return false;
        }
        Pattern pattern = Pattern.compile("^[1-9]\\d*$");
        Matcher match = pattern.matcher(str);
        return match.matches();
    }

    // 必须确保List<String> 里面的都是数字
    public static String numListToString(List<String> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }

        StringBuilder result = new StringBuilder();
        for (String s : list) {
            if (isPositiveNum(s)) {
                result.append(s).append(",");
            }
        }
        if (result.length() > 0 && result.toString().endsWith(",")) {
            result.deleteCharAt(result.length() - 1);
        }
        return result.toString();
    }

    public static List<String> stringToStringArrayList(String str) {
        List<String> list = new ArrayList<String>();
        if (str != null) {
            for (String s : str.split(",")) {
                if (isPositiveNum(s)) {
                    list.add(s);
                }
            }
        }
        return list;
    }

    public static List<Integer> stringToIntegerArrayList(String str) {
        List<Integer> list = new ArrayList<Integer>();
        if (str != null) {
            String[] t = str.split(",");
            for (String s : t) {
                if ("".equals(s)) {
                    continue;
                }
                if (ValidateUtil.isInteger(s)) {
                    list.add(Integer.parseInt(s));
                }
            }
        }
        return list;
    }
}
